home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 7: Sunsite / Linux Cubed Series 7 - Sunsite Vol 1.iso / system / admin / shadow-9.tar / shadow-9 / shadow-960129 / sulogin.c < prev    next >
C/C++ Source or Header  |  1995-12-17  |  8KB  |  305 lines

  1. /*
  2.  * Copyright 1989 - 1994, John F. Haugh II
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by John F. Haugh, II
  16.  *      and other contributors.
  17.  * 4. Neither the name of John F. Haugh, II nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY JOHN HAUGH AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL JOHN HAUGH OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifdef SVR4
  35. #include <utmpx.h>
  36. #else
  37. #include <sys/types.h>
  38. #include <utmp.h>
  39. #endif
  40. #include <signal.h>
  41. #include <stdio.h>
  42. #include "pwd.h"
  43. #include <fcntl.h>
  44. #include "config.h"
  45. #include "prototypes.h"
  46. #include "defines.h"
  47. #include "pwauth.h"
  48.  
  49. #if defined(BSD) || defined(SUN)
  50. #include <sgtty.h>
  51. #define    USE_SGTTY    1
  52. #endif
  53. #if defined(USG) || defined(SUN4)
  54. #ifdef    _POSIX_SOURCE
  55. #include <termios.h>
  56. #define    USE_TERMIOS    1
  57. #else
  58. #include <termio.h>
  59. #define    USE_TERMIO    1
  60. #endif
  61. #endif
  62.  
  63. #ifdef    USE_SYSLOG
  64. #include <syslog.h>
  65.  
  66. #ifndef    LOG_WARN
  67. #define    LOG_WARN    LOG_WARNING
  68. #endif
  69. #endif
  70.  
  71. #ifndef    lint
  72. static char rcsid[] = "$Id: sulogin.c,v 1.2 1995/12/16 21:51:39 marekm Exp $";
  73. #endif
  74.  
  75. char    name[BUFSIZ];
  76. char    pass[BUFSIZ];
  77.  
  78. struct    passwd    pwent;
  79. #ifdef SVR4
  80. struct    utmpx    utent;
  81. #else
  82. struct    utmp    utent;
  83. #endif
  84.  
  85. #ifdef    USE_SGTTY
  86. struct    sgttyb    termio;
  87. #endif
  88. #ifdef    USE_TERMIO
  89. struct    termio    termio;
  90. #endif
  91. #ifdef    USE_TERMIOS
  92. struct    termios    termio;
  93. #endif
  94.  
  95. #ifndef    MAXENV
  96. #define    MAXENV    64
  97. #endif
  98.  
  99. char    *newenvp[MAXENV];
  100. int    newenvc = 0;
  101. int    maxenv = MAXENV;
  102. extern    char    **environ;
  103. extern    char    *getpass();
  104.  
  105. extern    char    *getdef_str();
  106.  
  107. #ifndef    ALARM
  108. #define    ALARM    60
  109. #endif
  110.  
  111. #ifndef    RETRIES
  112. #define    RETRIES    3
  113. #endif
  114.  
  115. SIGTYPE
  116. catch (sig)
  117. int    sig;
  118. {
  119.     exit (1);
  120. }
  121.  
  122. /*ARGSUSED*/
  123. int
  124. main (argc, argv, envp)
  125. int    argc;
  126. char    **argv;
  127. char    **envp;
  128. {
  129.     char    *getenv ();
  130.     char    *ttyname ();
  131.     char    *getpass ();
  132.     char    *tz ();
  133.     char    *cp;
  134.  
  135. #ifdef    USE_SGTTY
  136.     ioctl (0, TIOCGETP, &termio);
  137.     termio.sg_flags |= (ECHO|CRMOD);
  138.     termio.sg_flags &= ~(RAW|CBREAK);
  139.     ioctl (0, TIOCSETN, &termio);
  140. #endif
  141. #ifdef    USE_TERMIO
  142.     ioctl (0, TCGETA, &termio);
  143.     termio.c_iflag |= (ICRNL|IXON);
  144.     termio.c_oflag |= (OPOST|ONLCR);
  145.     termio.c_cflag |= (CREAD);
  146.     termio.c_lflag |= (ISIG|ICANON|ECHO|ECHOE|ECHOK);
  147.     ioctl (0, TCSETAF, &termio);
  148. #endif
  149. #ifdef    USE_TERMIOS
  150.     tcgetattr (0, &termio);
  151.     termio.c_iflag |= (ICRNL|IXON);
  152.     termio.c_oflag |= (CREAD);
  153.     termio.c_lflag |= (ECHO|ECHOE|ECHOK|ICANON|ISIG);
  154.     tcsetattr (0, TCSANOW, &termio);
  155. #endif
  156. #ifdef    USE_SYSLOG
  157.     openlog ("sulogin", LOG_PID|LOG_CONS|LOG_NOWAIT, LOG_AUTH);
  158. #endif
  159.     if (argc > 1) {
  160.         close (0);
  161.         close (1);
  162.         close (2);
  163.  
  164.         if (open (argv[1], O_RDWR) >= 0) {
  165.             dup (0);
  166.             dup (0);
  167.         } else {
  168. #ifdef    USE_SYSLOG
  169.             syslog (LOG_WARN, "cannot open %s\n", argv[1]);
  170.             closelog ();
  171. #endif
  172.             exit (1);
  173.         }
  174.     }
  175.     if (access (PASSWD_FILE, 0) == -1) { /* must be a password file! */
  176.         printf ("No password file\n");
  177. #ifdef    USE_SYSLOG
  178.         syslog (LOG_WARN, "No password file\n");
  179.         closelog ();
  180. #endif
  181.         exit (1);
  182.     }
  183. #ifndef    DEBUG
  184.     if (getppid () != 1) {        /* parent must be INIT */
  185. #ifdef    USE_SYSLOG
  186.         syslog (LOG_WARN, "Pid == %d, not 1\n", getppid ());
  187.         closelog ();
  188. #endif
  189.         exit (1);
  190.     }
  191. #endif
  192.     if (! isatty (0) || ! isatty (1) || ! isatty (2)) {
  193. #ifdef    USE_SYSLOG
  194.         closelog ();
  195. #endif
  196.         exit (1);        /* must be a terminal */
  197.     }
  198.     while (*envp)            /* add inherited environment, */
  199.         addenv (*envp++);    /* some variables change later */
  200.  
  201.     if ((cp = getdef_str("ENV_TZ")))
  202.         addenv (*cp == '/' ? tz(cp) : cp);
  203.     if ((cp = getdef_str("ENV_HZ")))
  204.         addenv (cp);        /* set the default $HZ, if one */
  205.     (void) strcpy (name, "root");    /* KLUDGE!!! */
  206.  
  207.     signal (SIGALRM, catch);    /* exit if the timer expires */
  208.     alarm (ALARM);            /* only wait so long ... */
  209.  
  210.     while (1) {        /* repeatedly get login/password pairs */
  211.         entry (name, &pwent);    /* get entry from password file */
  212.         if (pwent.pw_name == (char *) 0) {
  213.  
  214.             /*
  215.              * Fail secure
  216.              */
  217.  
  218.             printf ("No password entry for 'root'\n");
  219. #ifdef    USE_SYSLOG
  220.             syslog (LOG_WARN, "No password entry for 'root'\n");
  221.             closelog ();
  222. #endif
  223.             exit (1);
  224.         }
  225.  
  226.     /*
  227.      * Here we prompt for the root password, or if no password is
  228.      * given we just exit.
  229.      */
  230.  
  231.                     /* get a password for root */
  232.         cp = getpass("Type control-d for normal startup,\n\
  233. (or give root password for system maintenance):");
  234.     /* XXX - can't enter single user mode if root password is empty.
  235.        I think this is rare :-).  But it will work with getpass()
  236.        from libc which doesn't return NULL on EOF.  --marekm */
  237.         if (!cp || !*cp) {
  238. #ifdef    USE_SYSLOG
  239.             syslog (LOG_INFO, "Normal startup\n");
  240.             closelog ();
  241. #endif
  242. #ifdef    TELINIT
  243.             execl (PATH_TELINIT, "telinit", RUNLEVEL, (char *) 0);
  244. #endif
  245.             exit (0);
  246.         } else {
  247.             STRFCPY(pass, cp);
  248.             bzero (cp, strlen (cp));
  249.         }
  250.         if (pwent.pw_name && pwent.pw_passwd[0] == '@') {
  251.             if (pw_auth (pwent.pw_passwd + 1, name, PW_LOGIN, (char *) 0)) {
  252. #ifdef    USE_SYSLOG
  253.                 syslog (LOG_WARN,
  254.                     "Incorrect root authentication");
  255. #endif
  256.                 continue;
  257.             }
  258.             goto auth_done;
  259.         }
  260.         if (valid (pass, &pwent)) /* check encrypted passwords ... */
  261.             break;        /* ... encrypted passwords matched */
  262.  
  263.         puts ("Login incorrect");
  264. #ifdef    USE_SYSLOG
  265.         syslog (LOG_WARN, "Incorrect root password\n");
  266. #endif
  267.     }
  268. auth_done:
  269.     bzero (pass, strlen (pass));
  270.     alarm (0);
  271.     signal (SIGALRM, SIG_DFL);
  272.     environ = newenvp;        /* make new environment active */
  273.  
  274.     puts ("Entering System Maintenance Mode");
  275. #ifdef    USE_SYSLOG
  276.     syslog (LOG_INFO, "System Maintenance Mode\n");
  277. #endif
  278.  
  279.     /*
  280.      * Normally there would be a utmp entry for login to mung on
  281.      * to get the tty name, date, etc. from.  We don't need all that
  282.      * stuff because we won't update the utmp or wtmp files.  BUT!,
  283.      * we do need the tty name so we can set the permissions and
  284.      * ownership.
  285.      */
  286.  
  287.     if ((cp = ttyname (0))) {        /* found entry in /dev/ */
  288.         if (strncmp(cp, "/dev/", 5) == 0)
  289.             cp += 5;
  290.  
  291.         strncpy(utent.ut_line, cp, sizeof utent.ut_line);
  292.     }
  293.     if (getenv ("IFS"))        /* don't export user IFS ... */
  294.         addenv ("IFS= \t\n");    /* ... instead, set a safe IFS */
  295.  
  296.     setup (&pwent);            /* set UID, GID, HOME, etc ... */
  297.  
  298. #ifdef    USE_SYSLOG
  299.     closelog ();
  300. #endif
  301.     shell (pwent.pw_shell, (char *) 0); /* exec the shell finally. */
  302.     /*NOTREACHED*/
  303.     return (0);
  304. }
  305.